package com.ushine.web.security.jwt;

import com.ushine.web.security.utils.RsaKeyConfig;
import com.ushine.web.security.utils.RsaUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;


/**
 * @Author yls
 * @Description 身份验证提供者
 * @Date 2020/4/6 9:33
 **/
public class JwtAuthenticationProvider extends DaoAuthenticationProvider {

    private RsaKeyConfig rsaKeyConfig;

    public void setRsaKeyConfig(RsaKeyConfig rsaKeyConfig) {
        this.rsaKeyConfig = rsaKeyConfig;
    }

    public JwtAuthenticationProvider(@Qualifier("securityUserServiceImpl") UserDetailsService userDetailsService,
                                     RsaKeyConfig rsaKeyConfig) {
        setUserDetailsService(userDetailsService);
        setRsaKeyConfig(rsaKeyConfig);
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            logger.debug("Authentication failed: no credentials provided");
            throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }

        String presentedPassword = authentication.getCredentials().toString();
        /**
         * RSA 解密
         */
        presentedPassword = RsaUtils.decrypt(presentedPassword, rsaKeyConfig.getPrivateKeyFile());
        // 覆写密码验证逻辑
        if (!new BCryptPasswordEncoder().matches(presentedPassword, userDetails.getPassword())) {
            logger.debug("Authentication failed: password does not match stored value");
            throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
    }

}